//! 日期时间工具模块
//! 
//! 对应Java中的AppDateMgr类，提供日期时间处理、格式化、转换等功能

use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Datelike, Weekday};
use std::time::{SystemTime, UNIX_EPOCH};

/// 日期格式常量
pub const YYYY_MM_DD_FORMAT: &str = "%Y-%m-%d";
pub const HH_MM_SS_FORMAT: &str = "%H:%M:%S";
pub const YYYY_MM_DD_HH_MM_SS_FORMAT: &str = "%Y-%m-%d %H:%M:%S";

/// 中国生肖
const CHINESE_ZODIAC: &[&str] = &["猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"];

/// 星座
const ZODIAC: &[&str] = &["水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", 
                         "狮子座", "处女座", "天秤座", "天蝎座", "射手座", "魔羯座"];

/// 星座日期边界
const ZODIAC_FLAGS: &[u32] = &[20, 19, 21, 21, 21, 22, 23, 23, 23, 24, 23, 22];

/// 获取当前时间戳（秒）
/// 
/// # Examples
/// ```
/// use librarys::date_utils::current_timestamp;
/// 
/// let timestamp = current_timestamp();
/// assert!(timestamp > 0);
/// ```
pub fn current_timestamp() -> i64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs() as i64
}

/// 获取当前时间戳（毫秒）
/// 
/// # Examples
/// ```
/// use librarys::date_utils::current_timestamp_millis;
/// 
/// let timestamp = current_timestamp_millis();
/// assert!(timestamp > 0);
/// ```
pub fn current_timestamp_millis() -> i64 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_millis() as i64
}

/// 获取当前日期字符串 (YYYY-MM-DD)
/// 
/// # Examples
/// ```
/// use librarys::date_utils::today_yyyy_mm_dd;
/// 
/// let today = today_yyyy_mm_dd();
/// assert!(today.len() == 10); // YYYY-MM-DD format
/// ```
pub fn today_yyyy_mm_dd() -> String {
    Local::now().format(YYYY_MM_DD_FORMAT).to_string()
}

/// 获取当前时间字符串 (HH:MM:SS)
/// 
/// # Examples
/// ```
/// use librarys::date_utils::today_hh_mm_ss;
/// 
/// let time = today_hh_mm_ss();
/// assert!(time.len() == 8); // HH:MM:SS format
/// ```
pub fn today_hh_mm_ss() -> String {
    Local::now().format(HH_MM_SS_FORMAT).to_string()
}

/// 获取当前日期时间字符串 (YYYY-MM-DD HH:MM:SS)
/// 
/// # Examples
/// ```
/// use librarys::date_utils::today_yyyy_mm_dd_hh_mm_ss;
/// 
/// let datetime = today_yyyy_mm_dd_hh_mm_ss();
/// assert!(datetime.len() == 19); // YYYY-MM-DD HH:MM:SS format
/// ```
pub fn today_yyyy_mm_dd_hh_mm_ss() -> String {
    Local::now().format(YYYY_MM_DD_HH_MM_SS_FORMAT).to_string()
}

/// 解析日期字符串为DateTime
/// 
/// # Examples
/// ```
/// use librarys::date_utils::parse_datetime;
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S");
/// assert!(dt.is_ok());
/// ```
pub fn parse_datetime(date_str: &str, format: &str) -> Result<DateTime<Local>, chrono::ParseError> {
    let naive_dt = NaiveDateTime::parse_from_str(date_str, format)?;
    Ok(Local.from_local_datetime(&naive_dt).single().unwrap())
}

/// 格式化DateTime为字符串
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{format_datetime, parse_datetime};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let formatted = format_datetime(&dt, "%Y/%m/%d");
/// assert_eq!(formatted, "2023/12/25");
/// ```
pub fn format_datetime(dt: &DateTime<Local>, format: &str) -> String {
    dt.format(format).to_string()
}

/// 获取年份
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, get_year};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// assert_eq!(get_year(&dt), 2023);
/// ```
pub fn get_year(dt: &DateTime<Local>) -> i32 {
    dt.year()
}

/// 获取月份
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, get_month};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// assert_eq!(get_month(&dt), 12);
/// ```
pub fn get_month(dt: &DateTime<Local>) -> u32 {
    dt.month()
}

/// 获取日期
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, get_day};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// assert_eq!(get_day(&dt), 25);
/// ```
pub fn get_day(dt: &DateTime<Local>) -> u32 {
    dt.day()
}

/// 获取星期几 (0=周日, 1=周一, ..., 6=周六)
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, get_weekday};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap(); // 周一
/// assert_eq!(get_weekday(&dt), 1);
/// ```
pub fn get_weekday(dt: &DateTime<Local>) -> u32 {
    match dt.weekday() {
        Weekday::Sun => 0,
        Weekday::Mon => 1,
        Weekday::Tue => 2,
        Weekday::Wed => 3,
        Weekday::Thu => 4,
        Weekday::Fri => 5,
        Weekday::Sat => 6,
    }
}

/// 获取一年中的第几周
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, get_week_of_year};
/// 
/// let dt = parse_datetime("2023-12-25 10:30:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let week = get_week_of_year(&dt);
/// assert!(week > 0 && week <= 53);
/// ```
pub fn get_week_of_year(dt: &DateTime<Local>) -> u32 {
    dt.iso_week().week()
}

/// 时间戳转日期时间字符串
/// 
/// # Examples
/// ```
/// use librarys::date_utils::timestamp_to_datetime;
/// 
/// let datetime_str = timestamp_to_datetime(1703505000); // 2023-12-25 10:30:00 UTC
/// assert!(datetime_str.contains("2023"));
/// ```
pub fn timestamp_to_datetime(timestamp: i64) -> String {
    let dt = Local.timestamp_opt(timestamp, 0).single().unwrap();
    format_datetime(&dt, YYYY_MM_DD_HH_MM_SS_FORMAT)
}

/// 日期时间字符串转时间戳
/// 
/// # Examples
/// ```
/// use librarys::date_utils::datetime_to_timestamp;
/// 
/// let timestamp = datetime_to_timestamp("2023-12-25 10:30:00");
/// assert!(timestamp.is_ok());
/// ```
pub fn datetime_to_timestamp(datetime_str: &str) -> Result<i64, chrono::ParseError> {
    let dt = parse_datetime(datetime_str, YYYY_MM_DD_HH_MM_SS_FORMAT)?;
    Ok(dt.timestamp())
}

/// 比较两个日期字符串，返回第一个是否在第二个之前
/// 
/// # Examples
/// ```
/// use librarys::date_utils::is_date_before;
/// 
/// let result = is_date_before("2023-12-24 10:00:00", "2023-12-25 10:00:00");
/// assert_eq!(result, true);
/// ```
pub fn is_date_before(date1: &str, date2: &str) -> bool {
    if let (Ok(dt1), Ok(dt2)) = (
        parse_datetime(date1, YYYY_MM_DD_HH_MM_SS_FORMAT),
        parse_datetime(date2, YYYY_MM_DD_HH_MM_SS_FORMAT)
    ) {
        dt1 < dt2
    } else {
        false
    }
}

/// 计算两个日期之间相差的分钟数
/// 
/// # Examples
/// ```
/// use librarys::date_utils::minutes_between;
/// 
/// let minutes = minutes_between("2023-12-25 10:00:00", "2023-12-25 11:30:00");
/// assert_eq!(minutes, 90);
/// ```
pub fn minutes_between(start_date: &str, end_date: &str) -> i64 {
    if let (Ok(start), Ok(end)) = (
        datetime_to_timestamp(start_date),
        datetime_to_timestamp(end_date)
    ) {
        (end - start) / 60
    } else {
        0
    }
}

/// 根据年份获取生肖
/// 
/// # Examples
/// ```
/// use librarys::date_utils::get_chinese_zodiac;
/// 
/// assert_eq!(get_chinese_zodiac(2023), "兔");
/// assert_eq!(get_chinese_zodiac(2024), "龙");
/// ```
pub fn get_chinese_zodiac(year: i32) -> &'static str {
    let index = (year % 12) as usize;
    CHINESE_ZODIAC[index]
}

/// 根据月日获取星座
/// 
/// # Examples
/// ```
/// use librarys::date_utils::get_zodiac;
/// 
/// assert_eq!(get_zodiac(3, 21), "白羊座");
/// assert_eq!(get_zodiac(12, 25), "魔羯座");
/// ```
pub fn get_zodiac(month: u32, day: u32) -> &'static str {
    if month < 1 || month > 12 || day < 1 || day > 31 {
        return "未知";
    }
    
    let month_index = (month - 1) as usize;
    if day >= ZODIAC_FLAGS[month_index] {
        ZODIAC[month_index]
    } else {
        let prev_index = if month_index == 0 { 11 } else { month_index - 1 };
        ZODIAC[prev_index]
    }
}

/// 判断是否为闰年
/// 
/// # Examples
/// ```
/// use librarys::date_utils::is_leap_year;
/// 
/// assert_eq!(is_leap_year(2024), true);
/// assert_eq!(is_leap_year(2023), false);
/// ```
pub fn is_leap_year(year: i32) -> bool {
    (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
}

/// 获取某月的天数
/// 
/// # Examples
/// ```
/// use librarys::date_utils::days_of_month;
/// 
/// assert_eq!(days_of_month(2023, 2), 28);
/// assert_eq!(days_of_month(2024, 2), 29);
/// assert_eq!(days_of_month(2023, 4), 30);
/// ```
pub fn days_of_month(year: i32, month: u32) -> u32 {
    match month {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        4 | 6 | 9 | 11 => 30,
        2 => if is_leap_year(year) { 29 } else { 28 },
        _ => 0,
    }
}

/// 格式化为友好的时间描述（几分钟前、几小时前等）
/// 
/// # Examples
/// ```
/// use librarys::date_utils::format_friendly;
/// use chrono::{Local, Duration};
/// 
/// let now = Local::now();
/// let past = now - Duration::minutes(30);
/// let friendly = format_friendly(&past);
/// assert!(friendly.contains("分钟前") || friendly.contains("小时前"));
/// ```
pub fn format_friendly(dt: &DateTime<Local>) -> String {
    let now = Local::now();
    let diff = now.signed_duration_since(*dt);
    
    if diff.num_days() > 365 {
        format!("{}年前", diff.num_days() / 365)
    } else if diff.num_days() > 30 {
        format!("{}个月前", diff.num_days() / 30)
    } else if diff.num_days() > 0 {
        format!("{}天前", diff.num_days())
    } else if diff.num_hours() > 0 {
        format!("{}个小时前", diff.num_hours())
    } else if diff.num_minutes() > 0 {
        format!("{}分钟前", diff.num_minutes())
    } else {
        "刚刚".to_string()
    }
}

/// 验证日期是否有效
/// 
/// # Examples
/// ```
/// use librarys::date_utils::is_valid_date;
/// 
/// assert_eq!(is_valid_date(2023, 2, 28), true);
/// assert_eq!(is_valid_date(2023, 2, 29), false);
/// assert_eq!(is_valid_date(2024, 2, 29), true);
/// ```
pub fn is_valid_date(year: i32, month: u32, day: u32) -> bool {
    if month < 1 || month > 12 {
        return false;
    }
    
    if day < 1 || day > days_of_month(year, month) {
        return false;
    }
    
    true
}

/// 获取指定日期的偏移日期
/// 
/// # Examples
/// ```
/// use librarys::date_utils::get_date_with_offset;
/// use chrono::Duration;
/// 
/// let date = get_date_with_offset(7); // 7天后
/// assert!(date.len() == 10);
/// ```
pub fn get_date_with_offset(offset_days: i64) -> String {
    let target_date = Local::now() + chrono::Duration::days(offset_days);
    format_datetime(&target_date, YYYY_MM_DD_FORMAT)
}

/// 判断两个日期是否是同一天
/// 
/// # Examples
/// ```
/// use librarys::date_utils::{parse_datetime, is_same_day};
/// 
/// let dt1 = parse_datetime("2023-12-25 10:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// let dt2 = parse_datetime("2023-12-25 15:00:00", "%Y-%m-%d %H:%M:%S").unwrap();
/// assert_eq!(is_same_day(&dt1, &dt2), true);
/// ```
pub fn is_same_day(dt1: &DateTime<Local>, dt2: &DateTime<Local>) -> bool {
    dt1.date_naive() == dt2.date_naive()
}

#[cfg(test)]
mod tests {
    use super::*;
    use chrono::Duration;

    #[test]
    fn test_current_functions() {
        let timestamp = current_timestamp();
        assert!(timestamp > 0);
        
        let timestamp_millis = current_timestamp_millis();
        assert!(timestamp_millis > timestamp * 1000);
        
        let today = today_yyyy_mm_dd();
        assert_eq!(today.len(), 10);
        
        let time = today_hh_mm_ss();
        assert_eq!(time.len(), 8);
        
        let datetime = today_yyyy_mm_dd_hh_mm_ss();
        assert_eq!(datetime.len(), 19);
    }

    #[test]
    fn test_parse_and_format() {
        let dt = parse_datetime("2023-12-25 10:30:00", YYYY_MM_DD_HH_MM_SS_FORMAT).unwrap();
        assert_eq!(get_year(&dt), 2023);
        assert_eq!(get_month(&dt), 12);
        assert_eq!(get_day(&dt), 25);
        
        let formatted = format_datetime(&dt, YYYY_MM_DD_FORMAT);
        assert_eq!(formatted, "2023-12-25");
    }

    #[test]
    fn test_timestamp_conversion() {
        let datetime_str = "2023-12-25 10:30:00";
        let timestamp = datetime_to_timestamp(datetime_str).unwrap();
        let converted_back = timestamp_to_datetime(timestamp);
        
        // 由于时区差异，我们只检查日期部分
        assert!(converted_back.contains("2023-12-25"));
    }

    #[test]
    fn test_date_comparison() {
        assert!(is_date_before("2023-12-24 10:00:00", "2023-12-25 10:00:00"));
        assert!(!is_date_before("2023-12-25 10:00:00", "2023-12-24 10:00:00"));
        
        let minutes = minutes_between("2023-12-25 10:00:00", "2023-12-25 11:30:00");
        assert_eq!(minutes, 90);
    }

    #[test]
    fn test_zodiac_and_chinese_zodiac() {
        assert_eq!(get_chinese_zodiac(2023), "兔");
        assert_eq!(get_chinese_zodiac(2024), "龙");
        
        assert_eq!(get_zodiac(3, 21), "白羊座");
        assert_eq!(get_zodiac(12, 25), "魔羯座");
    }

    #[test]
    fn test_leap_year() {
        assert!(is_leap_year(2024));
        assert!(!is_leap_year(2023));
        assert!(is_leap_year(2000));
        assert!(!is_leap_year(1900));
    }

    #[test]
    fn test_days_of_month() {
        assert_eq!(days_of_month(2023, 2), 28);
        assert_eq!(days_of_month(2024, 2), 29);
        assert_eq!(days_of_month(2023, 4), 30);
        assert_eq!(days_of_month(2023, 1), 31);
    }

    #[test]
    fn test_date_validation() {
        assert!(is_valid_date(2023, 2, 28));
        assert!(!is_valid_date(2023, 2, 29));
        assert!(is_valid_date(2024, 2, 29));
        assert!(!is_valid_date(2023, 13, 1));
        assert!(!is_valid_date(2023, 1, 32));
    }

    #[test]
    fn test_friendly_format() {
        let now = Local::now();
        let past = now - Duration::minutes(30);
        let friendly = format_friendly(&past);
        assert!(friendly.contains("分钟前"));
    }

    #[test]
    fn test_same_day() {
        let dt1 = parse_datetime("2023-12-25 10:00:00", YYYY_MM_DD_HH_MM_SS_FORMAT).unwrap();
        let dt2 = parse_datetime("2023-12-25 15:00:00", YYYY_MM_DD_HH_MM_SS_FORMAT).unwrap();
        let dt3 = parse_datetime("2023-12-26 10:00:00", YYYY_MM_DD_HH_MM_SS_FORMAT).unwrap();
        
        assert!(is_same_day(&dt1, &dt2));
        assert!(!is_same_day(&dt1, &dt3));
    }
}